#include "Blocks/FenceGateBlock.h"

#include "Engine/Point3.hpp"
#include "Managers/BlocksManager.h"
#include "Components/ComponentMiner.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentCreatureModel.h"
#include "Subsystems/SubsystemTerrain.h"

#include "GameSingleton.h"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    FenceGateBlock::FenceGateBlock()
    {
        addInheritance(this);
        addInheritance(dynamic_cast<IPaintableBlock *>(this));
    }

    void FenceGateBlock::getCreativeValues(std::vector<int32_t> &blockVec)
    {
        blockVec.push_back(Terrain::MakeBlockValue(getIndex(), 0, SetColor(0, -1)));
        for (int32_t index = 0; index < 16; ++index)
        {
            blockVec.push_back(Terrain::MakeBlockValue(getIndex(), 0, SetColor(0, index)));
        }
    }
    void FenceGateBlock::getDropValues(int32_t oldValue, int32_t newValue, int32_t toolLevel, std::vector<BlockDropValue> &dropValues)
    {
        int32_t data = SetVariant(Terrain::ExtractData(oldValue), 0);
        dropValues.push_back(BlockDropValue{Terrain::MakeBlockValue(getIndex(), 0, data), 1});
    }

    BlockPlacementData FenceGateBlock::getPlacementValue(ComponentMiner *componentMiner, int32_t value, const TerrainRaycastResult &raycastResult)
    {
        Vector3 forward = componentMiner->componentCreature->componentCreatureModel->getEyeRotation().toMatrix().getForward();
        float numBuff[4] = {
            Vector3::Dot(forward, FastVector3::UnitZ),
            Vector3::Dot(forward, FastVector3::UnitX),
            Vector3::Dot(forward, FastVector3::DecUnitZ),
            Vector3::Dot(forward, FastVector3::DecUnitX)
        };
        uint32_t targetIndex = MathUtils::MaxIndex<float>(numBuff, 4);
        int32_t rotation = 0;
        switch (targetIndex)
        {
        case 0:
            rotation = 2;
            break;
        case 1:
            rotation = 3;
            break;
        case 2:
            rotation = 0;
            break;
        case 3:
            rotation = 1;
            break;
        }
        Point3 point = CellFace::FaceToPoint3(raycastResult.cellFace.face);
        int32_t num6 = raycastResult.cellFace.point.posX + point.posX;
        int32_t y = raycastResult.cellFace.point.posY + point.posY;
        int32_t num7 = raycastResult.cellFace.point.posZ + point.posZ;
        int32_t num8 = 0;
        int32_t num9 = 0;
        switch (rotation)
        {
        case 0:
            num8 = -1;
            break;
        case 1:
            num9 = 1;
            break;
        case 2:
            num8 = 1;
            break;
        default:
            num9 = -1;
            break;
        }
        SubsystemTerrain *subsystemTerrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();
        int32_t cellValue = subsystemTerrain->getCellValue(num6 + num8, y, num7 + num9);
        int32_t cellValue2 = subsystemTerrain->getCellValue(num6 - num8, y, num7 - num9);
        Block *block = GameSingleton::blocksManager->blocks[Terrain::ExtractContents(cellValue)];
        Block *block2 = GameSingleton::blocksManager->blocks[Terrain::ExtractContents(cellValue2)];
        int32_t data = Terrain::ExtractData(cellValue);
        int32_t data2 = Terrain::ExtractData(cellValue2);
        bool rightHanded = (block->isBlock<FenceGateBlock *>() == true && GetRotation(data) == rotation) || ((block2->isBlock<FenceGateBlock *>() == false || GetRotation(data2) != rotation) && block->IsCollidable == false);
        int32_t data3 = SetRightHanded(SetOpen(SetRotation(Terrain::ExtractData(value), rotation), false), rightHanded);
        BlockPlacementData result;
        result.value = Terrain::ReplaceData(Terrain::ReplaceContents(0, getIndex()), data3);
        result.cellFace = raycastResult.cellFace;
        return result;
    }

    int32_t FenceGateBlock::getPaintColor(int32_t value)
    {
        return GetColor(Terrain::ExtractData(value));
    }
    int32_t FenceGateBlock::paint(int32_t value, int32_t color)
    {
        return Terrain::MakeBlockValue(getIndex(), 0, SetColor(Terrain::ExtractData(value), color));
    }

} // namespace PocketSurvival
